package models

import (
	"database/sql"
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"
)

func (*Struct物品列表) TableName() string {
	return "物品列表"
}

type 行属性 struct {
	V新建   bool
	V修改   bool
	V更新字段 map[string]bool //存放这个物品更新了哪些字段
	//V删除   bool
}

/*
			 	武器			帽			腿
	剑士   	OHWarrior     Warrior		Warrior
	斗士      Fighter		  Warrior		Warrior
	红法		Magician      Magician		Magician
	弓手		Archer		  Archer        Archer
	蓝法      Magician      Magician      Magician
*/
type Struct物品列表 struct {
	Id    int32   `xorm:"autoincr"`
	V信息ID int32   `xorm:"信息id"`
	V售价   int64   `xorm:"售价"` //这是商店向外出售的价格
	V修理价格 int64   `xorm:"修理价格"`
	V名称颜色 byte    `xorm:"名称颜色"` //0白色 1绿色 2金色 3暗金色 4紫色
	V中文名称 string  `xorm:"中文名称"`
	V数量   uint16  `xorm:"数量"`
	V当前耐久 float32 `xorm:"当前耐久"`
	V总耐久  float32 `xorm:"总耐久"`
	V限时道具 bool    `xorm:"限时道具"`
	V可否交易 bool    `xorm:"可否交易"` //不可交易，同时也不可以丢弃
	V是否绑定 bool    `xorm:"是否绑定"`
	V附加属性 string  `xorm:"附加属性"` //物品使用红宝石后的属性 第一个int为编号0,1,2,3... 第二个为属性+等级
	V物品倍率 float32 `xorm:"物品倍率"` //1 1.1 1.15装备
	Stata 行属性     `xorm:"-"`
}

type S基础属性 struct {
	Id  uint16 `xorm:"autoincr"`
	V名称 string `xorm:"'名称'"`
}

func (*S基础属性) TableName() string {
	return "基础属性"
}

func (z *Struct物品列表) 物品_获取附加属性值(属性名称 string) int {
	if len(z.V附加属性) == 0 {
		return 0
	}
	行 := strings.Split(z.V附加属性, "\n")
	for _, v := range 行 {
		sp := strings.Split(v, " ")
		if len(sp) != 2 {
			continue
		}
		if sp[0] == 属性名称 {
			if t, err := strconv.Atoi(sp[1]); err != nil {
				return 0
			} else {
				return t
			}
		}
	}
	return 0
}

//功能 创建一个物品，并在全局添加
func 物品_拆分物品(物品 *Struct物品列表, 分出数量 uint16) (*Struct物品列表, error) {
	新物品 := &Struct物品列表{}
	if 物品.V数量 == 0 {
		panic("不带数量的物品")
	}
	if 物品.V数量 < 分出数量 {
		return nil, errors.New("数量不够!")
	}

	新物品.V售价 = 物品.V售价
	新物品.V修理价格 = 物品.V修理价格
	新物品.V信息ID = 物品.V信息ID
	新物品.V名称颜色 = 物品.V名称颜色
	新物品.V中文名称 = 物品.V中文名称
	新物品.V数量 = 分出数量
	新物品.V当前耐久 = 物品.V当前耐久
	新物品.V总耐久 = 物品.V总耐久
	新物品.V限时道具 = 物品.V限时道具
	新物品.V可否交易 = 物品.V可否交易
	新物品.V附加属性 = 物品.V附加属性

	新物品.Id = GetTempId()
	新物品.Stata.V新建 = true //标记为新建
	新物品.Stata.V更新字段 = make(map[string]bool)
	return 新物品, nil
}

//功能 创建一个物品，并在全局添加
func 创建物品(panid int32) *Struct物品列表 {
	if panid >= 0 {
		panic(fmt.Sprintf("创建物品的ID不能大于0,当前ID:%d", panid))
	}
	新物品 := &Struct物品列表{}
	参考物品, err := 物品_获取系统物品列表(panid)
	if err != nil {
		panic("参考物品不存在:" + strconv.Itoa(int(panid)))
	}
	{
		新物品.V售价 = 参考物品.V售价
		新物品.V修理价格 = 参考物品.V修理价格
		新物品.V信息ID = 参考物品.V信息ID
		新物品.V名称颜色 = 参考物品.V名称颜色
		新物品.V中文名称 = 参考物品.V中文名称
		新物品.V数量 = 参考物品.V数量
		新物品.V当前耐久 = 参考物品.V当前耐久
		新物品.V总耐久 = 参考物品.V总耐久
		新物品.V限时道具 = 参考物品.V限时道具
		新物品.V可否交易 = 参考物品.V可否交易
		新物品.V附加属性 = 参考物品.V附加属性
	}
	新物品.Id = GetTempId()
	新物品.Stata.V新建 = true //标记为新建
	新物品.Stata.V更新字段 = make(map[string]bool)
	//m_物品列表.Store(新物品.Id, 新物品)
	return 新物品
}
func (rt *RunTime) 物品_简要信息(tx *Buff, wp *Struct物品列表) {
	物品信息 := 物品_获取物品信息(wp.V信息ID)
	tx.AddStringAndLen(物品信息.V外观2D)
	tx.AddInt32(int32(物品信息.V等级))
	//开始输出附加属性
	txi := len(tx.Buff) //保存位置
	tx.AddByte(0x00)
	maplen := 0
	/*for _, v := range strings.Split(wp.V附加属性, "\n") {
		if maplen >= 4 { //只能有4个属性,多了就会出错
			break
		}
		sp := strings.Split(v, " ")
		属性等级 := 1
		if len(sp) == 2 {
			if t, err := strconv.Atoi(sp[1]); err == nil {
				属性等级 = t
			}
		}
		var 英文名, 中文名 string
		if 属性信息, ok := m_附加属性信息[sp[0]]; ok == true {
			英文名 = 属性信息.V英文名
			中文名 = 属性信息.V中文名
		} else {
			continue
		}
		t := fmt.Sprintf("%s%02d", 英文名, 属性等级)
		tx.AddStringAndLen(t)
		tx.AddStringAndLen(fmt.Sprintf("%s Lv.%d", 中文名, 属性等级))
		maplen++
	}*/
	tx.Buff[txi] = byte(maplen) //写入长度
	tx.AddStringAndLen(物品信息.V外观3D)
	tx.AddStringAndLen(wp.V中文名称)
	tx.AddInt32(0)
	tx.AddByte(wp.V名称颜色)
	tx.AddInt32(物品信息.V持久开关1)
	Z := int32(0)
	if rt.V角色内容 != nil {
		Z = rt.V角色内容.Z
	}
	tx.AddInt32(Z) //88 EC FF FF
	tx.AddInt32(int32(物品信息.V宽度))
	tx.AddInt32(int32(物品信息.V高度))
	tx.AddInt32(0)
	tx.AddByte(0x01)           //必须是0x01 否则无法登录
	tx.AddByte(byte(物品信息.V种族)) //必须是0x01 否则无法登录
	tx.AddInt32(0x00)
}
func (rt *RunTime) 物品_物品信息(buff *Buff, wp *Struct物品列表) {
	物品信息 := 物品_获取物品信息(wp.V信息ID)
	buff.AddStringAndLen(物品信息.V外观2D)
	buff.AddInt32(int32(物品信息.V等级))
	buff.AddByte(wp.V名称颜色)
	buff.AddStringAndLen(物品信息.V外观3D)
	buff.AddStringAndLen(物品信息.V英文名称)

	合成名称 := strings.Split(wp.V中文名称, "\n")[0] //为了频道
	属性数量 := 砸宝_获取物品属性个数(wp)
	if 属性数量 > 4 {
		合成名称 += fmt.Sprintf("(%d转)", 属性数量-4)
	}
	buff.AddStringAndLen(合成名称)
	buff.AddStringAndLen(物品信息.V备注)
	buff.AddInt32(0)
	buff.AddInt32(int32(物品信息.V宽度))
	buff.AddInt32(int32(物品信息.V高度))
	buff.AddStringAndLen(物品信息.V类型)
	buff.AddInt32(物品信息.V持久开关1)
	buff.AddInt32(物品信息.V持久开关2)
	buff.AddFloat(wp.V当前耐久)
	buff.AddFloat(wp.V总耐久)
	buff.AddBool(物品信息.V数量)
	if 物品信息.V数量 == true {
		if wp.V数量 == 0 {
			wp.V数量 = 1
		}
		buff.AddInt32(int32(wp.V数量))
	}
	buff.AddInt64(售价(wp.V售价))
	buff.AddInt64(wp.V修理价格)
	buff.AddBool(wp.V限时道具)
	buff.AddBool(wp.V可否交易)
	buff.AddBool(wp.V可否交易)
	buff.AddBool(wp.V可否交易)
	buff.AddBool(wp.V是否绑定)
	buff.AddInt32(物品信息.V集中力)
	buff.AddInt32(物品信息.V分散力)
	buff.AddByte(物品信息.V后续封包格式)
	输出封包(buff, wp)
}
func 输出封包(buff *Buff, wp *Struct物品列表) {
	物品信息 := 物品_获取物品信息(wp.V信息ID)
	switch 物品信息.V后续封包格式 {
	case 0x00: //项链
		buff.AddByte(0x01) //未知
		buff.AddInt32(int32(物品信息.V穿戴位置))
		buff.AddInt32(物品信息.V种族)
		buff.AddInt32(物品信息.V职业)
	case 0x02: //药瓶
		for i := uint16(0); i < 2; i++ {
			n := int32(0)
			if iv, ok := 物品信息.V封包属性[i]; ok == true {
				n = int32(iv)
			}
			buff.AddInt32(n)
		}
		buff.AddBytes(String2Byte("64000000000000000000"))
	case 0x04: //武器
		buff.AddFloat(wp.V物品倍率) //100 115 105装备
		buff.AddInt32(1000)
		buff.AddFloat(0.16)
		//buff.AddBytes(String2Byte("2900A20200000000"))
		武器S := []uint16{E基础属性_最小物理攻击力, E基础属性_最大物理攻击力,
			E基础属性_最小魔法攻击力, E基础属性_最大魔法攻击力,
			E基础属性_亡灵系最小攻击力, E基础属性_亡灵系最大攻击力,
			E基础属性_生物系最小攻击力, E基础属性_生物系最大攻击力,
			E基础属性_召唤系最小攻击力, E基础属性_召唤系最大攻击力,
			E基础属性_突变系最小攻击力, E基础属性_突变系最大攻击力,
			E基础属性_人类系最小攻击力, E基础属性_人类系最大攻击力,
			E基础属性_精灵系最小攻击力, E基础属性_精灵系最大攻击力,
			E基础属性_精灵系最小攻击力, E基础属性_精灵系最大攻击力}
		for _, v := range 武器S {
			n := int32(0)
			if iv, ok := 物品信息.V封包属性[v]; ok == true {
				n = int32(iv)
			}
			buff.AddInt32(n)
		}
		buff.AddByte(0x01)
		buff.AddInt32(int32(物品信息.V穿戴位置))
		buff.AddInt32(物品信息.V种族)
		buff.AddInt32(物品信息.V职业)
	case 0x05: //防御类
		buff.AddFloat(0x01)
		fy := make([]int, 4) //第一个 物理防御 第二个物理防御力  第三个魔法防御 第四个 魔法防御力
		if v, ok := 物品信息.V封包属性[E基础属性_物理防御力]; ok == true {
			fy[0] = int(v)
		}
		if v, ok := 物品信息.V封包属性[E基础属性_物理防御千分比]; ok == true {
			fy[1] = int(v)
		}
		if v, ok := 物品信息.V封包属性[E基础属性_魔法防御力]; ok == true {
			fy[2] = int(v)
		}
		if v, ok := 物品信息.V封包属性[E基础属性_魔法防御千分比]; ok == true {
			fy[3] = int(v)
		}
		s := ""
		if fy[0] != 0 {
			s += fmt.Sprintf("%d+%d", fy[0], fy[1])
		}
		if fy[2] != 0 {
			if len(s) != 0 {
				s += "   "
			}
			s += fmt.Sprintf("魔法防御力 %d+%d ", fy[2], fy[3])
		}
		buff.AddStringAndLen(s)
		buff.AddByte(0x01)
		buff.AddInt32(int32(物品信息.V穿戴位置))
		buff.AddInt32(物品信息.V种族)
		buff.AddInt32(物品信息.V职业)
	case 06: //护盾
		buff.AddFloat(wp.V物品倍率)
		buff.AddInt32(0x0AD7233D)
		buff.AddByte(0x01)
		buff.AddInt32(int32(物品信息.V穿戴位置))
		buff.AddInt32(物品信息.V种族)
		buff.AddInt32(物品信息.V职业)
	case 0x07: //ETC
		if 物品信息.V穿戴位置 == 1024 {
			频道 := strings.Split(wp.V中文名称, "\n")
			if len(频道) > 1 {
				buff.AddStringAndLen(频道[1])
			} else {
				buff.AddStringAndLen("")
			}
		} else {
			buff.AddStringAndLen("未知N")
		}
		buff.AddByte(0x01)
		buff.AddInt32(int32(物品信息.V穿戴位置))
		buff.AddInt32(物品信息.V种族)
		buff.AddInt32(物品信息.V职业)
	case 0x0A:
		for i := uint16(0); i < 8; i++ {
			n := int32(0)
			if iv, ok := 物品信息.V封包属性[i]; ok == true {
				n = int32(iv)
			} else if i == 0 {
				n = 0x3D4CCCCD //三级箭筒
			}
			buff.AddInt32(n)
		}
		buff.AddBytes(String2Byte("01800000000200000000020000"))
	case 0x0C: //小凯旋
		buff.AddInt16(0x00)
		buff.AddInt32(0x00)
	case 0x12: //技能书
	//19 00 00 00 53 65 63 6F 6E 64 5F 49 74 65 6D 5F 46 69 72 65 46 75 72 79 5F 4C 76 37 00 01 00 00 00 00 17 00 00 00 53 65 63 6F 6E 64 53 6B 69 6C 6C 42 6F 6F 6B 5F 70 75 72 70 6C 65 00 0E 00 00 00 BB F0 D6 AE C5 AD 20 B5 C8 BC B6 20 37 00 12 00 00 00 37 BC B6 B7 DF C5 AD D6 AE BB F0 BC BC C4 DC CA E9 00 2F 00 00 00 5B BA EC C4 A7 B7 A8 CA A6 D3 C3 5D 7C 7C 4C 76 37 20 B7 DF C5 AD D6 AE BB F0 3A 7C B6 D4 B5 A5 D2 BB C4 BF B1 EA D4 EC B3 C9 C9 CB BA A6 00 00 00 00 00 02 00 00 00 02 00 00 00 04 00 00 00 55 73 65 00 29 00 00 00 00 00 00 00 00 00 80 BF 00 00 80 BF 00 C0 27 09 00 00 00 00 00 FF FF FF FF FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 12 00 00 00 00 00 00 19 00 00 00 0A 14 00 00 14 00 00 00 00 00 00 00 00 00 00 00 1E 14 84 00 0A 00 00 00 47 61 75 67 65 43 6F 69 6E 00 00 00 00 00 0A 14 00 00 0E 00 00 00 00 00 00 00 00 00 00 00 04 14 47 01 01 00 00 00 00 00 00 00 00 00 00 00
	case 0x14:
		buff.AddInt16(0x00)
		buff.AddInt32(0x00)
	case 0x016: //宠物
		jsonmap := make(map[string]interface{})
		json.Unmarshal([]byte(wp.V附加属性), &jsonmap)
		英文名称 := ""
		if obj, ok := jsonmap["英文名称"]; ok == true {
			英文名称 = obj.(string)
		}
		buff.AddStringAndLen(英文名称)
		中文名称 := ""
		if obj, ok := jsonmap["中文名称"]; ok == true {
			中文名称 = obj.(string)
		}
		buff.AddStringAndLen(中文名称)
		攻击点数 := int32(0)
		if obj, ok := jsonmap["攻击点数"]; ok == true {
			攻击点数 = int32(obj.(float64))
		}
		buff.AddInt32(0x04)
		buff.AddInt32(攻击点数)

		背包点数 := int32(0)
		if obj, ok := jsonmap["背包点数"]; ok == true {
			背包点数 = int32(obj.(float64))
		}
		buff.AddInt32(背包点数)
		HP点数 := int32(0)
		if obj, ok := jsonmap["HP点数"]; ok == true {
			HP点数 = int32(obj.(float64))
		}
		buff.AddInt32(HP点数)

		MP点数 := int32(0)
		if obj, ok := jsonmap["MP点数"]; ok == true {
			MP点数 = int32(obj.(float64))
		}
		buff.AddInt32(MP点数)

		宠物点数 := int32(0)
		if obj, ok := jsonmap["宠物点数"]; ok == true {
			宠物点数 = int32(obj.(float64))
		}
		buff.AddInt32(宠物点数)
		buff.AddInt32(0x01)
		buff.AddInt32(0x00)
		buff.AddByte(0x00)
		buff.AddByte(0x00)
		buff.AddByte(0x00)
		buff.AddInt32(0x4C)
	case 0x19: //腰带
		buff.AddFloat(0x01) //1.0 1.05 1.15
		buff.AddStringAndLen("111+555")
		for i := uint16(0); i < 7; i++ {
			n := int32(0)
			if iv, ok := 物品信息.V封包属性[i]; ok == true {
				n = int32(iv)
			}
			buff.AddInt32(n)
		}
		buff.AddByte(0x01) //未知
		buff.AddInt32(int32(物品信息.V穿戴位置))
		buff.AddInt32(物品信息.V种族)
		buff.AddInt32(物品信息.V职业)
	default:
		panic("未知后续封包格式")
	}
	switch 物品信息.V后续封包格式 {
	case 0x00, 0x04, 0x05, 0x06, 0x07, 0x0A, 0x19:
		txi := len(buff.Buff) //保存位置
		buff.AddByte(0x00)    //			str += "后续参数个数:" + GetByteString(ref s, 1, false) + "\t";
		maplen := 0
		for i := uint8(0); i < 9; i++ {
			n := int32(0)
			if iv, ok := 物品信息.V属性要求[i]; ok == true {
				n = int32(iv)
			} else {
				continue
			}
			buff.AddByte(byte(i))
			buff.AddInt32(n)
			maplen++
		}
		buff.Buff[txi] = byte(maplen) //写入长度
		buff.AddBytes(String2Byte("0000000000"))
		txi = len(buff.Buff) //保存位置
		buff.AddByte(0x00)
		maplen = 0
		for _, v := range strings.Split(wp.V附加属性, "\n") {
			sp := strings.Split(v, " ")
			属性等级 := 1
			if len(sp) == 2 {
				if t, err := strconv.Atoi(sp[1]); err == nil {
					属性等级 = t
				}
			}
			var 英文名, 中文名 string
			if 属性信息, ok := m_附加属性信息[sp[0]]; ok == true {
				英文名 = 属性信息.V英文名
				中文名 = 属性信息.V中文名
			} else {
				英文名 = "unkonw"
				中文名 = "未知属性名称"
			}
			t := fmt.Sprintf("%s%02d", 英文名, 属性等级*10/int(m_物品最亮等级))
			buff.AddStringAndLen(t)
			buff.AddStringAndLen(fmt.Sprintf("%s Lv.%d", 中文名, 属性等级))
			maplen++
		}
		buff.Buff[txi] = byte(maplen) //写入长度
	}
}

func 物品_解析并添加物品(buff *Buff) string {
	ret := time.Now().Format("15:04:05") + " 准备分析:\r\n"
	物品信息 := &Struct物品信息{}
	物品 := &Struct物品列表{}
	物品信息.V外观2D = buff.GetStringAndLen()
	物品信息.V等级 = uint8(buff.GetInt32())
	物品.V名称颜色 = buff.GetByte()
	物品信息.V外观3D = buff.GetStringAndLen()
	物品信息.V英文名称 = buff.GetStringAndLen()
	物品.V中文名称 = buff.GetStringAndLen()
	物品信息.V备注 = buff.GetStringAndLen()
	buff.GetInt32()
	物品信息.V宽度 = uint8(buff.GetInt32())
	物品信息.V高度 = uint8(buff.GetInt32())
	物品信息.V类型 = buff.GetStringAndLen()
	物品信息.V持久开关1 = buff.GetInt32()
	物品信息.V持久开关2 = buff.GetInt32()
	物品.V当前耐久 = buff.GetFloat()
	物品.V总耐久 = buff.GetFloat()
	物品信息.V数量 = buff.GetBool()
	if 物品信息.V数量 == true {
		物品.V数量 = uint16(buff.GetInt32())
	}
	物品.V售价 = buff.GetInt64()
	物品.V修理价格 = buff.GetInt64()
	物品.V限时道具 = buff.GetBool()
	物品.V可否交易 = buff.GetBool()
	buff.GetBool()
	buff.GetBool()
	物品.V是否绑定 = buff.GetBool()
	物品信息.V集中力 = buff.GetInt32()
	物品信息.V分散力 = buff.GetInt32()
	物品信息.V后续封包格式 = buff.GetByte()
	获取封包(buff, 物品, 物品信息)
	//先判断物品信息是否存在
	if _, ok := 物品_获取物品信息_2D(物品信息.V外观2D); ok != nil {
		m_物品信息最小ID--
		物品信息.Id = m_物品信息最小ID
		if _, err := db.Insert(物品信息); err != nil {
			ret += err.Error() + "\r\n"
		} else {
			ret += fmt.Sprintln("添加物品信息:", 物品信息.V外观2D)
		}
	}
	m_物品列表最小ID--
	物品.Id = m_物品列表最小ID
	物品.V信息ID = 物品信息.Id
	if 物品.V物品倍率 == 0 {
		物品.V物品倍率 = 1
	}
	if _, err := db.Insert(物品); err != nil {
		ret += err.Error() + "\r\n"
	} else {
		ret += fmt.Sprintln("添加物品信息:", 物品.V中文名称)
	}
	return ret
}
func 获取封包(buff *Buff, 物品 *Struct物品列表, 物品信息 *Struct物品信息) {
	switch 物品信息.V后续封包格式 {
	case 0x00: //项链
		t := buff.GetByte() //未知
		if t == 0 {         //后面的数据就不要了
			return
		}
		物品信息.V穿戴位置 = uint16(buff.GetInt32())
		物品信息.V种族 = buff.GetInt32()
		物品信息.V职业 = buff.GetInt32()
	case 0x02: //药瓶
		for i := uint16(0); i < 2; i++ {
			物品信息.V封包属性[i] = float32(buff.GetInt32())
		}
		buff.GetBytes(10)
	case 0x04: //武器
		物品.V物品倍率 = buff.GetFloat() //100 115 105装备
		buff.GetBytes(8)
		武器S := []uint16{E基础属性_最小物理攻击力, E基础属性_最大物理攻击力,
			E基础属性_最小魔法攻击力, E基础属性_最大魔法攻击力,
			E基础属性_亡灵系最小攻击力, E基础属性_亡灵系最大攻击力,
			E基础属性_生物系最小攻击力, E基础属性_生物系最大攻击力,
			E基础属性_召唤系最小攻击力, E基础属性_召唤系最大攻击力,
			E基础属性_突变系最小攻击力, E基础属性_突变系最大攻击力,
			E基础属性_人类系最小攻击力, E基础属性_人类系最大攻击力,
			E基础属性_精灵系最小攻击力, E基础属性_精灵系最大攻击力,
			E基础属性_精灵系最小攻击力, E基础属性_精灵系最大攻击力}
		for _, v := range 武器S {
			值 := buff.GetInt32()
			if 值 != 0 {
				物品信息.V封包属性[v] = float32(值)
			}
		}
		buff.GetByte()
		物品信息.V穿戴位置 = uint16(buff.GetInt32())
		物品信息.V种族 = buff.GetInt32()
		物品信息.V职业 = buff.GetInt32()
	case 0x05: //防御类
		物品.V物品倍率 = buff.GetFloat()
		s := buff.GetStringAndLen()
		fmt.Printf("防御类,请分析内容:%s", s)
		buff.GetByte()
		物品信息.V穿戴位置 = uint16(buff.GetInt32())
		物品信息.V种族 = buff.GetInt32()
		物品信息.V职业 = buff.GetInt32()
	case 06: //护盾
		物品.V物品倍率 = buff.GetFloat()
		buff.GetInt32()
		buff.GetByte()
		物品信息.V穿戴位置 = uint16(buff.GetInt32())
		物品信息.V种族 = buff.GetInt32()
		物品信息.V职业 = buff.GetInt32()
	case 0x07: //ETC
		if 物品信息.V穿戴位置 == 1024 {
			物品信息.V备注 = buff.GetStringAndLen()
		} else {
			fmt.Printf("ETC手工解析:%s", buff.GetStringAndLen())
		}
		buff.GetByte()
		物品信息.V穿戴位置 = uint16(buff.GetInt32())
		物品信息.V种族 = buff.GetInt32()
		物品信息.V职业 = buff.GetInt32()
	case 0x0A:
		物品.V物品倍率 = buff.GetFloat()
		for i := uint16(1); i < 8; i++ {
			值 := float32(buff.GetInt32())
			if 值 != 0 {
				物品信息.V封包属性[i] = 值
			}
		}
		buff.GetBytes(13)
	case 0x0C: //小凯旋
		buff.GetInt16()
		buff.GetInt32()
	case 0x14:
		buff.GetInt16()
		buff.GetInt32()
	case 0x016: //宠物
		jsonmap := make(map[string]interface{})
		jsonmap["英文名称"] = buff.GetStringAndLen()
		jsonmap["中文名称"] = buff.GetStringAndLen()
		jsonmap["攻击点数"] = buff.GetInt32()
		jsonmap["背包点数"] = buff.GetInt32()
		jsonmap["HP点数"] = buff.GetInt32()
		jsonmap["MP点数"] = buff.GetInt32()
		jsonmap["宠物点数"] = buff.GetInt32()
		if t, err := json.Marshal(&jsonmap); err == nil {
			物品.V附加属性 = string(t)
		} else {
			fmt.Println("宠物信息转换出错:", err)
		}
		buff.GetInt32()
		buff.GetInt32()
		buff.GetByte()
		buff.GetByte()
		buff.GetByte()
		buff.GetInt32()
	case 0x19: //腰带
		物品.V物品倍率 = buff.GetFloat() //1.0 1.05 1.15
		s := buff.GetStringAndLen()
		fmt.Printf("腰带类，手工解析:%s", s)
		for i := uint16(0); i < 7; i++ {
			值 := float32(buff.GetInt32())
			if 值 != 0 {
				物品信息.V封包属性[i] = 值
			}
		}
		buff.GetByte() //未知
		物品信息.V穿戴位置 = uint16(buff.GetInt32())
		物品信息.V种族 = buff.GetInt32()
		物品信息.V职业 = buff.GetInt32()
	default:
		物品信息.V后续封包格式 = 0
		return
		//fmt.Sprintf("未知后续封包格式:%d", 物品信息.V后续封包格式)
	}
	switch 物品信息.V后续封包格式 {
	case 0x00, 0x04, 0x05, 0x06, 0x07, 0x0A, 0x19:
		数量 := buff.GetByte()
		for i := uint8(0); i < 数量; i++ {
			index := buff.GetByte()
			物品信息.V属性要求[index] = buff.GetInt32()
		}
		buff.GetBytes(5)
		数量 = buff.GetByte()
		for i := byte(0); i < 数量; i++ {
			物品信息.V英文名称 = buff.GetStringAndLen()
			物品.V中文名称 = buff.GetStringAndLen()
		}
	}
}
func Fun加载物品(ids []int32) []*Struct物品列表 {
	var ret []*Struct物品列表
	if len(ids) == 0 {
		return ret
	}
	var wplb []*Struct物品列表
	if err := db.In("id", ids).Find(&wplb); err != nil {
		panic(err)
	}
	for _, v := range wplb {
		v.Stata.V更新字段 = make(map[string]bool)
		ret = append(ret, v)
	}
	return ret
}

func 物品_获取物品信息(id int32) *Struct物品信息 {
	if m_缓存表 == true {
		if t, ok := m_物品信息[id]; ok == true {
			return t
		}
	}
	ret := &Struct物品信息{Id: id}
	if ok, _ := db.Get(ret); ok == false {
		return nil
	}
	ret.V封包属性 = make(map[uint16]float32)
	for 名称, 值 := range ret.V封包属性_ {
		属性ID := m_基础属性[名称]
		ret.V封包属性[属性ID] = 值
	}
	if m_缓存表 == true {
		m_物品信息[id] = ret
		m_物品信息_外观2D[ret.V外观2D] = ret
	}
	return ret
}

func 物品_获取系统物品列表(id int32) (*Struct物品列表, error) {
	if m_缓存表 == true {
		if t, ok := m_系统物品列表2[id]; ok == true {
			return t, nil
		}
	}
	ret := &Struct物品列表{Id: id}
	if ok, _ := db.Get(ret); ok == false {
		return nil, sql.ErrNoRows
	}
	return ret, nil
}
func 物品_获取系统物品列表_中文(name string) (*Struct物品列表, error) {
	if m_缓存表 == true {
		if t, ok := m_系统物品列表_中文2[name]; ok == true {
			return t, nil
		}
	}
	ret := &Struct物品列表{}
	if ok, _ := db.Where("中文名称=?", name).Get(ret); ok == false {
		return nil, sql.ErrNoRows
	}
	return ret, nil
}
func 物品_获取物品信息_2D(name2d string) (*Struct物品信息, error) {
	if m_缓存表 == true {
		if t, ok := m_物品信息_外观2D[name2d]; ok == true {
			return t, nil
		}
	}
	ret := &Struct物品信息{}
	if ok, _ := db.Where("外观2D=?", name2d).Get(ret); ok == false {
		return nil, sql.ErrNoRows
	}
	ret.F同步数据(m_基础属性)
	if m_缓存表 == true {
		m_物品信息[ret.Id] = ret
		m_物品信息_外观2D[ret.V外观2D] = ret
	}
	return ret, nil
}
